﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

///<summary>
///用于网络发送与接收部份的测试类
///</summary>

namespace wifi_test
{
    class cls_testnet
    {
        private UdpClient   cls_SendUdp;// = new UdpClient();
        private IPEndPoint  cls_destendpoint; 
        private UdpClient   cls_RecUdp;  
        private IPEndPoint  cls_localendpoint;
        public Form1 MF;
        
        public cls_record  record_cls = new cls_record();

        private int _recPackets;
        public int recPackets
        {
            get
            {
                return _recPackets;
            }
        }

        private int _sendPackets = 0;
        public int sendPackets
        {
            get
            {
                return _sendPackets; ;
            }
            set
            {
                _sendPackets = value;
            }
        }

        private int _recErrors;
        public int recErrors
        {
            get
            {
                return _recErrors;
            }
            set
            {
                _recErrors = value;
            }
        }

        private int _sendErrors;
        public int sendErrors
        {
            get
            {
                return _sendErrors;
            }
        }

        private int _recframeno;
        private int _recMiss;
        public int recMiss
        {
            get
            {
                return _recMiss;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="mf"></param>
        public cls_testnet(Form1 mf)
        {
            
            MF = mf;
        }
         
        /// <summary>
        /// 初始本机向目标机进行发送部份程序
        /// </summary>
        /// <param name="destIpText">目标机的IP地址</param>
        /// <param name="destPort">目标机的端口号</param>
        /// <returns></returns>
        public bool fun_InitSendInterface(String destIpText, int destPort)
        {
            bool retflag;
            IPAddress tmp_address;

            retflag = false;
            try
            {
                tmp_address = System.Net.IPAddress.Parse(destIpText);
            }
            catch (FormatException e)
            {
                retflag = false;
                return retflag;
            }
            catch (Exception e)
            {
                retflag = false;
                return retflag;
            }

            try
            {
                cls_destendpoint = new IPEndPoint(tmp_address, destPort);
            }
            catch (ArgumentOutOfRangeException e)
            {
                retflag = false;
                return retflag;
            }

            retflag = true;
            return retflag;
        }


        /// <summary>
        /// 对本地的接收部份的代码
        /// </summary>
        /// <param name="localIpStr">本机的IP地址</param>
        /// <param name="localPort">本机的端口号</param>
        /// <returns></returns>
        public bool fun_InitRecInterface(String localIpStr, int localPort)
        {
            bool retflag;

            retflag = false;

            IPAddress tmp_address;

            retflag = false;
            try
            {
                tmp_address = System.Net.IPAddress.Parse(localIpStr);
            }
            catch (FormatException e)
            {
                retflag = false;
                return retflag;
            }
            catch (Exception e)
            {
                retflag = false;
                return retflag;
            }

            try
            {
                cls_localendpoint = new IPEndPoint(tmp_address, localPort);
                //cls_localendpoint = new IPEndPoint(IPAddress.Any, 0);
            }
            catch (ArgumentOutOfRangeException e)
            {
                retflag = false;
                return retflag;
            }

            cls_SendUdp = new UdpClient(localPort);
            //cls_RecUdp = new UdpClient(localPort);
            

            retflag = true;
            return retflag;
        }


        /// <summary>
        /// 创建要发送的测试帧
        /// </summary>
        /// <param name="frameno">这一帧的帧号</param>
        /// 帧的第一个字节为帧号：帧号从0开始到9
        /// 帧全长为1021个字节(第一个为帧号)从大写字母A一直循环到J
        /// 每个字母填充102个字节到帧中去，从那个字母开始根据帧号
        /// 决定。
        /// <returns></returns>
        public byte[] fun_CreateFrame(byte frameno)
        {
            byte [] send_buf = new byte[1021];             

            int i;
            int j, k;

            j = frameno;
            k = 1;
            for (i = 0; i < 10; i++)
            {
                for (int z = 0; z < 102; z++)
                {
                    int h;

                    h = j + 'A';
                    send_buf[k] = (byte)h;
                    k += 1;
                }
                j += 1;
                if (j > 9)
                {
                    j = 0;
                }
            }

            send_buf[0] = frameno;
            return send_buf;
        }


        /// <summary>
        /// 发送已经生成好的数据包
        /// </summary>
        /// <param name="data"></param>
        public void sub_SendFrame(byte[] data)
        {
            int i;

            i = cls_SendUdp.Send(data, data.Length, cls_destendpoint);
        }


        /// <summary>
        /// 启动接收目标所发送出来的数据异步模式
        /// </summary>
        /// 返回空数组表示没有数据接收到
        /// <returns></returns>
        public bool fun_RecDstDataStart()
        {
            bool retflag;

            retflag = false;

            cls_RecUdp.BeginReceive(new AsyncCallback(ReceiveCallback), this);


            return retflag;
        }


        /// <summary>
        /// 接收下位机发送数据的回调函数
        /// </summary>
        /// <param name="ar"></param>
        public static void ReceiveCallback(IAsyncResult ar)
        {
            cls_testnet parent_cls = (cls_testnet)(ar.AsyncState);

            Byte[] receiveBytes = parent_cls.cls_RecUdp.EndReceive(ar, ref parent_cls.cls_localendpoint);

        }


        /// <summary>
        /// 接收目标所送出来的数据阻塞
        /// </summary>
        /// <returns></returns>
        public byte[] fun_RecDstData()
        {
            IPEndPoint sendAddress = new IPEndPoint(IPAddress.Any, 0);

            //byte[] retbuf = cls_RecUdp.Receive(ref sendAddress);
            byte[] retbuf;
            try
            {
                retbuf = cls_SendUdp.Receive(ref sendAddress);
                if (sendAddress.Address.ToString() != cls_destendpoint.Address.ToString())
                {
                    //地址不相等
                    retbuf = null;
                }
            }
            catch (Exception e)
            {
                //MF.xulog(Form1.LogMsgType.Warning, e.ToString() + "\n");
                retbuf = null;
            }

            return retbuf;
        }


        /// <summary>
        /// 设置希望接收到的帧号
        /// </summary>
        /// <param name="p_frameno">希望接收到的帧号</param>
        public void sub_SetRecFrameNo(int p_frameno)
        {
            _recframeno = p_frameno;
        }


        /// <summary>
        ///  对送入的帧数据进行分析
        /// </summary>
        /// 返回：100表示握手成功了。
        /// 返回：-1这帧不是所期望接收到的帧
        /// 返回：0不做任何处理
        /// 返回： 1这帧是所期望的接收到的帧
        /// <param name="framedata">接收到的帧数据</param>
        /// <returns></returns>
        public int fun_AnalyFrame(byte[] framedata, Form1.TestState currentState)
        {
            int ret = 0;
            int i;
            byte[] tmpbuf;

            switch (currentState)
            {
                case Form1.TestState.handshake:
                    //处于握手的状态
                    tmpbuf = new byte[2];

                    if (framedata.Length > 1)
                    {
                        Array.Copy(framedata, tmpbuf, 2);
                        if ((tmpbuf[0] == 111) && (tmpbuf[1] == 107))
                        {
                            ret = 100;
                            _recPackets = 0;
                        }
                        else
                        {
                            ret = 0;
                        }
                    }
                    break;

                case Form1.TestState.sendhandshake:
                    //处于要发送握手的状态
                    string xustr11 = "ok";
                    tmpbuf = System.Text.Encoding.Default.GetBytes(xustr11);
                    sub_SendFrame(tmpbuf);

                    _recPackets = 0;
                    _sendPackets = 0;
                    ret = 100;
                    break;

                case Form1.TestState.testing:
                    //进行对接收到的包进行判断
                    _recPackets += 1;
                    if (_recframeno == -1)
                    {
                        //刚握手成功还没有接收到过数据
                        _recframeno = framedata[0] + 1;
                        if (_recframeno > 9)
                        {
                            _recframeno = 0;
                        }
                    }
                    else
                    {
                        //要对数据进行判断是否是我要的数据
                        if (_recframeno == framedata[0])
                        {
                            byte dstfirstbyte;

                            dstfirstbyte = 65;
                            dstfirstbyte += (byte)_recframeno;    //第一个102个字节的内容要为a+帧号
                            i = fun_comparadata(framedata, dstfirstbyte);
                            if (i == -1)
                            {
                                //出错了，要调整一下要接收帧号了
                                //要记录下出错的信息了
                                
                                string xustr = "接收帧号" + _recframeno.ToString() + "内容出错";
                                //MF.xulog(Form1.LogMsgType.Error, xustr + "\n");
                                record_cls.sub_recordin(cls_record.recordstate.recerror, xustr);
                                _recErrors += 1;
                                _recframeno += 1;
                            }
                        }
                        else
                        {
                            //比较出错了
                            /*if (((framedata[0] == 0) && (_recframeno == 9)) || ((_recframeno == 9) && (framedata[0] == 0)))
                            {
                                i = 1;
                            }
                            else if (framedata[0] > _recframeno)
                            {
                                i = framedata[0] - _recframeno;
                            }
                            else
                            {
                                i = _recframeno - framedata[0];
                            }
                            string xustr = "希望接收帧号" + _recframeno.ToString() + "--实际接收帧号" 
                                            + framedata[0].ToString() + "--掉失" + i.ToString();

                            _recMiss += i;
                            record_cls.sub_recordin(cls_record.recordstate.recerror, xustr);
                            
                            //MF.xulog(Form1.LogMsgType.Error, xustr + "\n");
                            //xulog()
                            _recframeno = framedata[0] + 1;*/
                        }

                        if (_recframeno > 9)
                        {
                            _recframeno = 0;
                        }
                    }
                    break;
            }
            return ret;
        }


        /// <summary>
        /// 对接收到的数据进行每102字一块的比较
        /// </summary>
        /// <param name="data_sp">接收到的数据</param>
        /// <param name="dstValue">第一个块应为的数据内容</param>
        /// <returns>
        /// 返回1正常
        /// 返回-1不是希望的
        /// </returns>
        private int fun_comparadata(byte[] data_sp, byte dstValue)
        {
            int ret = 1;
            int i;
            byte tmpbyte;

            tmpbyte = dstValue;
            for (i = 0; i < 10; i++)
            {
                for (int j = 0; j < 102; j++)
                {
                    if (data_sp[i * 102 + j + 1] != tmpbyte)
                    {
                        ret = -1;
                        break;
                    }
                }

                tmpbyte += 1;
                if ((tmpbyte - 65) > 9)
                {
                    tmpbyte = 65;
                }

                if (ret == -1)
                {
                    break;
                }
            }

            return ret;
        }


        /// <summary>
        /// 重新初始化相关的参数
        /// </summary>
        public void sub_reinit()
        {
            cls_SendUdp.Close();
            _sendErrors = 0;
            _recErrors = 0;
            _sendErrors = 0;
            _recPackets = 0;
            _recMiss = 0;
            //cls_RecUdp.Close();
        }

    }
}
